using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using CodePlex.TfsLibrary;
using CodePlex.TfsLibrary.ObjectModel;
using CodePlex.TfsLibrary.RepositoryWebSvc;

namespace CodePlex.UnitTestUtility
{
    public class StubSourceControlService : ISourceControlService
    {
        public SourceItem[] _MultiItem;
        public SourceItem[] _SingleDirectory;
        public SourceItem[] _SingleFile;
        public bool AddWorkspaceMapping__ThrowsCredExceptionOnce = false;
        public ICredentials AddWorkspaceMapping_Credentials;
        public string AddWorkspaceMapping_LocalPath;
        public string AddWorkspaceMapping_ServerPath;
        public string AddWorkspaceMapping_TfsUrl;
        public string AddWorkspaceMapping_WorkspaceName;
        public int Commit__Result = 42;
        public string Commit_Comment;
        public ICredentials Commit_Credentials;
        public List<string> Commit_ServerItems;
        public string Commit_TfsUrl;
        public bool Commit_ThrowsCredExceptionOnce = false;
        public string Commit_WorkspaceName;
        public bool CreateWorkspace__Called = false;
        public bool CreateWorkspace__ThrowsCredExceptionOnce = false;
        public ICredentials CreateWorkspace_Credentials;
        public string CreateWorkspace_TfsUrl;
        public string CreateWorkspace_WorkspaceName;
        public bool DeleteWorkspace__ThrowException = false;
        public ICredentials DeleteWorkspace_Credentials;
        public string DeleteWorkspace_TfsUrl;
        public string DeleteWorkspace_WorkspaceName;
        public int GetLatestChangeset__Result;
        public ICredentials GetLatestChangeset_Credentials;
        public string GetLatestChangeset_TfsUrl;
        public List<LocalUpdate> GetLocalUpdates__Result;
        public ICredentials GetLocalUpdates_Credentials;
        public bool GetLocalUpdates_ForceGetAll;
        public RecursionType GetLocalUpdates_Recursion;
        public string GetLocalUpdates_ServerPath;
        public string GetLocalUpdates_TfsUrl;
        public VersionSpec GetLocalUpdates_Version;
        public string GetLocalUpdates_WorkspaceName;
        public ICredentials PendChanges_Credentials;
        public List<PendRequest> PendChanges_Requests;
        public string PendChanges_TfsUrl;
        public string PendChanges_WorkspaceName;
        public bool QueryItems__Called = false;
        public SourceItem[] QueryItems__Result;
        public bool QueryItems__ThrowsCredExceptionOnce = false;
        public ICredentials QueryItems_Credentials;
        public DeletedState QueryItems_DeletedState;
        public ItemType QueryItems_ItemType;
        public RecursionType QueryItems_Recursion;
        public string QueryItems_ServerPath;
        public string QueryItems_TfsUrl;
        public VersionSpec QueryItems_VersionSpec;
        public bool QueryLog__Called = false;
        public bool QueryLog__ThrowsCredExceptionOnce = false;
        public ICredentials QueryLog_Credentials;
        public int QueryLog_MaxCount;
        public RecursionType QueryLog_RecursionType;
        public LogItem QueryLog_Result;
        public string QueryLog_ServerPath;
        public string QueryLog_TfsUrl;
        public VersionSpec QueryLog_VersionFrom;
        public VersionSpec QueryLog_VersionTo;
        public ICredentials UpdateLocalVersions_Credentials;
        public string UpdateLocalVersions_TfsUrl;
        public List<LocalUpdate> UpdateLocalVersions_Updates;
        public string UpdateLocalVersions_WorkspaceName;
        public ICredentials UploadFile_Credentials;
        public string UploadFile_LocalPath;
        public string UploadFile_ServerPath;
        public string UploadFile_TfsUrl;
        public string UploadFile_WorkspaceName;
        public ICredentials UploadFileFromBytes_Credentials;
        public byte[] UploadFileFromBytes_LocalContents;
        public string UploadFileFromBytes_ServerPath;
        public string UploadFileFromBytes_TfsUrl;
        public string UploadFileFromBytes_WorkspaceName;
        public ICredentials UploadFileFromStream_Credentials;
        public Stream UploadFileFromStream_LocalContents;
        public string UploadFileFromStream_ServerPath;
        public string UploadFileFromStream_TfsUrl;
        public string UploadFileFromStream_WorkspaceName;

        public StubSourceControlService()
        {
            SourceItem root = SourceItem.FromRemoteItem(0, ItemType.Folder, "$/Foo", 0, -1L, DateTime.MinValue, null);
            SourceItem item1 = SourceItem.FromRemoteItem(1, ItemType.File, "$/Foo/file1.txt", 5, -1L, DateTime.MinValue, "durl1");
            SourceItem item2 = SourceItem.FromRemoteItem(2, ItemType.File, "$/Foo/file2.txt", 6, -1L, DateTime.MinValue, "durl2");
            SourceItem item3 = SourceItem.FromRemoteItem(3, ItemType.Folder, "$/Foo/folder", 7, -1L, DateTime.MinValue, null);
            SourceItem item4 = SourceItem.FromRemoteItem(4, ItemType.File, "$/Foo/file4.txt", 8, -1L, DateTime.MinValue, "durl4");

            _SingleFile = new SourceItem[] { root, item1 };
            _SingleDirectory = new SourceItem[] { root, item3 };
            _MultiItem = new SourceItem[] { root, item1, item2, item3, item4 };

            QueryItems__Result = _SingleFile;

            SourceItemHistory logHistory = new SourceItemHistory(42, "username", DateTime.Now, "Comment");
            QueryLog_Result = new LogItem(null, "$/Foo/bar.txt", new SourceItemHistory[1] { logHistory });

            GetLocalUpdates__Result = new List<LocalUpdate>();
        }

        public void AddWorkspaceMapping(string tfsUrl,
                                        ICredentials credentials,
                                        string workspaceName,
                                        string serverPath,
                                        string localPath)
        {
            if (AddWorkspaceMapping__ThrowsCredExceptionOnce)
            {
                AddWorkspaceMapping__ThrowsCredExceptionOnce = false;
                throw new NetworkAccessDeniedException();
            }

            AddWorkspaceMapping_TfsUrl = tfsUrl;
            AddWorkspaceMapping_Credentials = credentials;
            AddWorkspaceMapping_WorkspaceName = workspaceName;
            AddWorkspaceMapping_ServerPath = serverPath;
            AddWorkspaceMapping_LocalPath = localPath;
        }

        public int Commit(string tfsUrl,
                          ICredentials credentials,
                          string workspaceName,
                          string comment,
                          IEnumerable<string> serverItems)
        {
            if (Commit_ThrowsCredExceptionOnce)
            {
                Commit_ThrowsCredExceptionOnce = false;
                throw new NetworkAccessDeniedException();
            }

            Commit_TfsUrl = tfsUrl;
            Commit_Credentials = credentials;
            Commit_WorkspaceName = workspaceName;
            Commit_Comment = comment;
            Commit_ServerItems = new List<string>(serverItems);

            return Commit__Result;
        }

        public void CreateWorkspace(string tfsUrl,
                                    ICredentials credentials,
                                    string workspaceName,
                                    string workspaceComment)
        {
            CreateWorkspace__Called = true;

            if (CreateWorkspace__ThrowsCredExceptionOnce)
            {
                CreateWorkspace__ThrowsCredExceptionOnce = false;
                throw new NetworkAccessDeniedException();
            }

            CreateWorkspace_TfsUrl = tfsUrl;
            CreateWorkspace_Credentials = credentials;
            CreateWorkspace_WorkspaceName = workspaceName;
        }

        public void DeleteWorkspace(string tfsUrl,
                                    ICredentials credentials,
                                    string workspaceName)
        {
            if (DeleteWorkspace__ThrowException)
                throw new Exception();

            DeleteWorkspace_TfsUrl = tfsUrl;
            DeleteWorkspace_Credentials = credentials;
            DeleteWorkspace_WorkspaceName = workspaceName;
        }

    	public Guid GetRepositoryId(string tfsUrl, ICredentials credentials)
    	{
    		throw new NotImplementedException();
    	}

    	public int GetLatestChangeset(string tfsUrl,
                                      ICredentials credentials)
        {
            GetLatestChangeset_TfsUrl = tfsUrl;
            GetLatestChangeset_Credentials = credentials;

            return GetLatestChangeset__Result;
        }

        [Obsolete]
        public LocalUpdate[] GetLocalUpdates(string tfsUrl,
                                             ICredentials credentials,
                                             string workspaceName,
                                             string serverPath,
                                             RecursionType recursion,
                                             VersionSpec version,
                                             bool forceGetAll)
        {
            GetLocalUpdates_TfsUrl = tfsUrl;
            GetLocalUpdates_Credentials = credentials;
            GetLocalUpdates_WorkspaceName = workspaceName;
            GetLocalUpdates_ServerPath = serverPath;
            GetLocalUpdates_Recursion = recursion;
            GetLocalUpdates_Version = version;
            GetLocalUpdates_ForceGetAll = forceGetAll;

            return GetLocalUpdates__Result.ToArray();
        }

        public WorkspaceInfo[] GetWorkspaces(string tfsUrl,
                                             ICredentials credentials,
                                             WorkspaceComputers computers)
        {
            throw new NotImplementedException();
        }

        public void PendChanges(string tfsUrl,
                                ICredentials credentials,
                                string workspaceName,
                                IEnumerable<PendRequest> requests)
        {
            PendChanges_TfsUrl = tfsUrl;
            PendChanges_Credentials = credentials;
            PendChanges_WorkspaceName = workspaceName;
            PendChanges_Requests = new List<PendRequest>(requests);
        }

        public SourceItem[] QueryItems(string tfsUrl,
                                       ICredentials credentials,
                                       string serverPath,
                                       RecursionType recursion,
                                       VersionSpec version,
                                       DeletedState deletedState,
                                       ItemType itemType)
        {
            QueryItems__Called = true;

            if (QueryItems__ThrowsCredExceptionOnce)
            {
                QueryItems__ThrowsCredExceptionOnce = false;
                throw new NetworkAccessDeniedException();
            }

            QueryItems_TfsUrl = tfsUrl;
            QueryItems_Credentials = credentials;
            QueryItems_ServerPath = serverPath;
            QueryItems_Recursion = recursion;
            QueryItems_VersionSpec = version;
            QueryItems_DeletedState = deletedState;
            QueryItems_ItemType = itemType;

            return QueryItems__Result;
        }

        public SourceItem[] QueryItems(string tfsUrl,
                                       ICredentials credentials,
                                       int[] itemIds,
                                       int changeSet)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public LogItem QueryLog(string tfsUrl,
                                ICredentials credentials,
                                string serverPath,
                                VersionSpec versionFrom,
                                VersionSpec versionTo,
                                RecursionType recursionType,
                                int maxCount)
        {
            QueryLog__Called = true;

            if (QueryLog__ThrowsCredExceptionOnce)
            {
                QueryLog__ThrowsCredExceptionOnce = false;
                throw new NetworkAccessDeniedException();
            }

            QueryLog_TfsUrl = tfsUrl;
            QueryLog_Credentials = credentials;
            QueryLog_ServerPath = serverPath;
            QueryLog_VersionFrom = versionFrom;
            QueryLog_VersionTo = versionTo;
            QueryLog_RecursionType = recursionType;
            QueryLog_MaxCount = maxCount;

            return QueryLog_Result;
        }

        public void UndoPendingChanges(string tfsUrl,
                                       ICredentials credentials,
                                       string workspaceName,
                                       IEnumerable<string> serverItems)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void UpdateLocalVersions(string tfsUrl,
                                        ICredentials credentials,
                                        string workspaceName,
                                        IEnumerable<LocalUpdate> updates)
        {
            UpdateLocalVersions_TfsUrl = tfsUrl;
            UpdateLocalVersions_Credentials = credentials;
            UpdateLocalVersions_WorkspaceName = workspaceName;
            UpdateLocalVersions_Updates = new List<LocalUpdate>(updates);
        }

        public void UploadFile(string tfsUrl,
                               ICredentials credentials,
                               string workspaceName,
                               string localPath,
                               string serverPath)
        {
            UploadFile_TfsUrl = tfsUrl;
            UploadFile_Credentials = credentials;
            UploadFile_WorkspaceName = workspaceName;
            UploadFile_LocalPath = localPath;
            UploadFile_ServerPath = serverPath;
        }

        public void UploadFileFromBytes(string tfsUrl,
                                        ICredentials credentials,
                                        string workspaceName,
                                        byte[] localContents,
                                        string serverPath)
        {
            UploadFileFromBytes_TfsUrl = tfsUrl;
            UploadFileFromBytes_Credentials = credentials;
            UploadFileFromBytes_WorkspaceName = workspaceName;
            UploadFileFromBytes_LocalContents = localContents;
            UploadFileFromBytes_ServerPath = serverPath;
        }

        public void UploadFileFromStream(string tfsUrl,
                                         ICredentials credentials,
                                         string workspaceName,
                                         Stream localContents,
                                         string serverPath)
        {
            UploadFileFromStream_TfsUrl = tfsUrl;
            UploadFileFromStream_Credentials = credentials;
            UploadFileFromStream_WorkspaceName = workspaceName;
            UploadFileFromStream_LocalContents = localContents;
            UploadFileFromStream_ServerPath = serverPath;
        }
    }
}